package gui;

import java.awt.*;
import java.awt.image.BufferedImage;

/**
 *	@(#)ImageRotator.java
 *
 *	The <code>ImageRotator</code> class is a utility class
 *	containing a method to rotate an image by a given angle.
 *
 *	@author Grzegorz Kobiela
 *	@version 1.0 2007/9/11
 */
public abstract class ImageRotator
{
	/**
	 *	Returns a <code>BufferedImage</code> instance containing
	 *	the given image rotated by the given angle.
	 *	@param src the source image
	 *	@param angle the angle in degrees
	 *	@return the rotated image
	 */
	public static BufferedImage rotate(Image src, int angle) {
		double phi = Math.toRadians(angle);
		int width = src.getWidth(null);
		int height = src.getHeight(null);

		/* Original bounds */
		Point a = new Point(0, 0);
		Point b = new Point(width, 0);
		Point c = new Point(0, height);
		Point d = new Point(width, height);

		/* Rotated bounds */
		Point newA = rotate(a, phi);
		Point newB = rotate(b, phi);
		Point newC = rotate(c, phi);
		Point newD = rotate(d, phi);

		/* Calculate new bounds */
		int w = Math.max(Math.max(newA.x, newB.x), Math.max(newC.x, newD.x)) - Math.min(Math.min(newA.x, newB.x), Math.min(newC.x, newD.x));
		int h = Math.max(Math.max(newA.y, newB.y), Math.max(newC.y, newD.y)) - Math.min(Math.min(newA.y, newB.y), Math.min(newC.y, newD.y));

		/* Create new image */
		BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = img.createGraphics();
		g.setTransform(java.awt.geom.AffineTransform.getRotateInstance(phi, w / 2, h / 2));
		g.drawImage(src, (w - width) / 2, (h - height) / 2, null);

		/* Return rotated image */
		return img;
 	}

 	/**
	 *	Returns an <code>ImageIcon</code> rotated by a given angle.
	 *	@param src source icon
	 *	@param angle angle in degrees
	 *	@return rotated icon
	 */
	public static javax.swing.ImageIcon rotate(javax.swing.ImageIcon src, int angle) {
		return new javax.swing.ImageIcon(rotate(src.getImage(), angle));
	}

	/**
	 *	Returns the given point rotated by the given angle.
	 *	@param p the point to rotate
	 *	@param angle the angle
	 *	@return the rotated point
	 */
	private static Point rotate(Point p, double angle) {
		double c = Math.cos(angle);
		double s = Math.sin(angle);
		return new Point((int)(p.x * c - p.y * s), (int)(p.x * s + p.y * c));
	}
}